#include "LogStream.h"
#include <cstdio>
#include <algorithm>

using namespace cyc;
using namespace cyc::detail;

namespace cyc
{
  namespace detail
  {

    const char digits[] = "0123456789";

    const char digitsHex[] = "0123456789ABCDEF";

    // Efficient Integer to String Conversions, by Matthew Wilson.
    template <typename T>
    size_t convert(char buf[], T value)
    {
      T i = value;
      char *p = buf;

      do
      {
        int lsd = static_cast<int>(i % 10);
        i /= 10;
        *p++ = digits[lsd];
      } while (i != 0);

      if (value < 0)
      {
        *p++ = '-';
      }
      *p = '\0';
      std::reverse(buf, p);

      return p - buf;
    }

  }
}

LogStream::LogStream(void)
{
}

LogStream::~LogStream(void)
{
}

LogStream &LogStream::operator<<(short v)
{
  *this << static_cast<int>(v);
  return *this;
}

LogStream &LogStream::operator<<(unsigned short v)
{
  *this << static_cast<unsigned int>(v);
  return *this;
}

LogStream &LogStream::operator<<(int v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(unsigned int v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(long v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(unsigned long v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(long long v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(unsigned long long v)
{
  formatInteger(v);
  return *this;
}

LogStream &LogStream::operator<<(const void *p)
{
  char temp[kMaxNumericSize];
  int len = snprintf(temp, kMaxNumericSize, "0x%08X", p);
  if (len)
    buffer_.append(temp, len);
  return *this;
}

// FIXME: replace this with Grisu3 by Florian Loitsch.
LogStream &LogStream::operator<<(double v)
{
  char temp[kMaxNumericSize];
  int len = snprintf(temp, kMaxNumericSize, "%.12g", v);
  if (len)
    buffer_.append(temp, len);
  return *this;
}

template <typename T>
void LogStream::formatInteger(T v)
{
  char temp[kMaxNumericSize];
  size_t len = convert(temp, v); // 在上面的实现中可以到，已经一步步把数据转化为字符放到缓冲区中
  buffer_.append(temp, len);     // 增加偏移长度
}